import java.awt.BorderLayout;
import java.awt.Font;
import java.awt.dnd.DnDConstants;
import java.awt.dnd.DragGestureRecognizer;
import java.awt.dnd.DragSource;
import java.awt.dnd.DropTarget;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.ArrayList;

import javax.swing.BoxLayout;
import javax.swing.JButton;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.border.EtchedBorder;

public class MainPanel extends JPanel {

	private static final long serialVersionUID = -8758661239146254980L;
	private final JLabel statusLabel = new JLabel();
	private ActionListener buttonActionListener;
	private final ServiceManager mng;
	private final JPanel servicesPanel;
	@SuppressWarnings("unused")
	private final JPanel statusPanel;
	private final DiagramPanel diagramPanel;
	@SuppressWarnings("unused")
	private final JPanel rightPanel;
	private ABCListener abcListener;
	private final DragSource dragSource;
	private final DragAndDropListener dragAndDropListener;
	@SuppressWarnings("unused")
	private final DropTarget dropTarget;
	private final ArrayList<DragGestureRecognizer> dragGestureRecognizers;

	public MainPanel(ServiceManager serviceManager) {
		mng = serviceManager;
		setLayout(new BorderLayout());
		createTestButtonActionListener();
		servicesPanel = addServicesPanel();
		rightPanel = addRightPanel();
		statusPanel = addStatusPanel();
		diagramPanel = addDiagramPanel();
		dragAndDropListener = new DragAndDropListener();
		dragSource = new DragSource();
		dropTarget = new DropTarget(diagramPanel, DnDConstants.ACTION_COPY, dragAndDropListener);
		dragGestureRecognizers = new ArrayList<DragGestureRecognizer>();
		addServiceItemsToServicePanel();
		addListeners();
		mng.getStatusService().post(Lang.get_Ready());
	}

	private void addListeners() {
		mng.addABCListener(createABCListener());
	}

	private ABCListener createABCListener() {
		abcListener = new ABCListener() {

			@Override
			public void drawServiceIcon(Service service, int x, int y) {
				diagramPanel.drawServiceIcon(service, x, y);
			}

			@Override
			public void clearServiceIcon(Service service) {
				diagramPanel.clearServiceIcon(service);
			}
		};
		return abcListener;
	}

	private void createTestButtonActionListener() {
		buttonActionListener = new ActionListener() {
			@Override
			public void actionPerformed(ActionEvent e) {
				mng.getStatusService().post(
						((JButton) e.getSource()).getText());
			}
		};
	}

	private JPanel addStatusPanel() {
		JPanel panel = addPanel(BorderLayout.SOUTH);
		panel.setLayout(new BorderLayout());
		statusLabel.setFont(statusLabel.getFont().deriveFont(Font.PLAIN));
		mng.addStatusService(new MessageEventListener() {
			@Override
			public void post(MessageEvent arg) {
				statusLabel.setText(arg.getMessage());
			}
		});
		panel.add(statusLabel, BorderLayout.WEST);
		return panel;
	}

	private DiagramPanel addDiagramPanel() {
		DiagramPanel panel = new DiagramPanel();  
		addPanel(panel, BorderLayout.CENTER);
		return panel;
	}

	private JPanel addRightPanel() {
		JPanel panel = addPanel(BorderLayout.EAST);
		addButton(panel, "Test 2");
		addButton(panel, "Test 3");
		addButton(panel, "Test 4");
		return panel;
	}

	private void addButton(JPanel panel, String title) {
		JButton button = new JButton(title);
		button.addActionListener(buttonActionListener);
		panel.add(button, BorderLayout.NORTH);
	}

	private JPanel addServicesPanel() {
		JPanel panel = addPanel(BorderLayout.WEST);
		panel.setLayout(new BoxLayout(servicesPanel, BoxLayout.Y_AXIS));
		return panel;
	}

	private void addServiceItemsToServicePanel() {
		ArrayList<Service> actionServices = mng.getActionServices();
		for (int i = 0; i < actionServices.size(); i++){
			ServiceItem serviceItem = new ServiceItem(actionServices.get(i));
			servicesPanel.add(serviceItem);
			dragGestureRecognizers.add(createDragGestureRecognizer(serviceItem));
		}
	}

	private DragGestureRecognizer createDragGestureRecognizer(ServiceItem serviceItem) {
		return dragSource.createDefaultDragGestureRecognizer(serviceItem, DnDConstants.ACTION_COPY, dragAndDropListener);
	}

	private JPanel addPanel(String layout) {
		return addPanel(new JPanel(), layout);
	}

	private JPanel addPanel(JPanel panel, String layout) {
		panel.setBorder(new EtchedBorder(EtchedBorder.RAISED));
		add(panel, layout);
		return panel;
	}
}
